package com.shanzmoo.h5.web;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.google.common.collect.Maps;
import com.shanzmoo.base.bean.SHttpResponse;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.constant.PayStatusConstant;
import com.shanzmoo.base.exception.PayException;
import com.shanzmoo.base.util.SResponseUtils;
import com.shanzmoo.core.config.pay.MyWxPayConfig;
import com.shanzmoo.core.pay.sdk.alipay.config.Configs;
import com.shanzmoo.core.pay.sdk.wxpay.WXPay;
import com.shanzmoo.core.util.SWxPayUtils;
import com.shanzmoo.db.sys.entity.vo.AddressTreeVo;
import com.shanzmoo.db.sys.service.IAddressService;
import com.shanzmoo.db.trade.entity.PayOrderEntity;
import com.shanzmoo.db.trade.service.IPayOrderCallbackService;
import com.shanzmoo.db.trade.service.IPayOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * 会员服务-开发接口
 * @author Gzhao 2021/1/3
 */
@Slf4j
@Api(tags = "会员服务-开发接口")
@RestController
@RequestMapping("open")
public class OpenController {

    @Autowired
    private IAddressService addressService;
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private IPayOrderCallbackService payOrderCallbackService;

    @GetMapping("addressTree")
    @ApiOperation(value = "地址树")
    public SHttpResponse<List<AddressTreeVo>> getAddressTree(){
        List<AddressTreeVo> re = addressService.getAddressTree();
        return SHttpResponse.ok(re);
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("支付宝回调")
    @PostMapping("/order/trade/callback/alipay")
    public void success(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> map = Maps.newHashMap();
        Enumeration<String> parameterNames = request.getParameterNames();

        while (parameterNames.hasMoreElements()) {
            String parameter = parameterNames.nextElement();
            log.info("parametername:{}, value:{}", parameter, request.getParameter(parameter));
            if (!parameter.toLowerCase().equals("sign_type")) {
                map.put(parameter, request.getParameter(parameter));
            }
        }

        try {
            boolean result = AlipaySignature.rsaCheckV2(map, Configs.getAlipayPublicKey(), "utf-8", Configs.getSignType());
            if (result) {
                // todo 支付成功处理
                SResponseUtils.outputStr(response, "success");
            } else {
                SResponseUtils.outputStr(response, "unSuccess");
            }
        } catch (AlipayApiException e) {
            throw new PayException("支付回调失败: " + e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("微信支付回调")
    @PostMapping("/order/trade/callback/wxpay")
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String notifyData = SWxPayUtils.obtainNotifyData(request);

        log.info("微信支付回调：{}", notifyData);

        Map<String, String> notifyMap = SWxPayUtils.convertMapAndSignType(notifyData);

        MyWxPayConfig config = new MyWxPayConfig();
        WXPay wxpay = new WXPay(config, true, false);

        // 回调返回微信信息
        String resXml;

        Boolean status = null;
        String payNo = notifyMap.get("out_trade_no");
        PayOrderEntity payOrderEntity = payOrderService.getByPayNo(payNo);

        if (payOrderEntity.getPayStatus() == PayStatusConstant.PAY_SUCCESS){
            resXml = SWxPayUtils.getWxpayCallbackSuccessReturn();
        } else {
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
                // 交易金额
                Integer totalFee = Integer.parseInt(notifyMap.get("total_fee"));

                if (payOrderEntity.getTotalFee().intValue() != totalFee.intValue()) {
                    log.error("微信支付回调失败!支付金额异常");

                    status = false;
                    resXml = SWxPayUtils.getWxpayCallbackFailReturn("支付金额异常");
                } else {

                    LocalDateTime finishTime = LocalDateTimeUtil.parse(notifyMap.get("time_end"), "yyyyMMddHHmmss");
                    SResponse<Boolean> re = payOrderService.updatePaySuccessStatus(payOrderEntity, finishTime);

                    if (re.getData()) {
                        status = true;
                        resXml = SWxPayUtils.getWxpayCallbackSuccessReturn();
                    } else {
                        log.error("微信支付回调处理失败! 业务逻辑处理异常");

                        status = false;
                        resXml = SWxPayUtils.getWxpayCallbackFailReturn("业务逻辑处理异常");
                    }
                }
            } else {
                log.error("微信支付回调失败!签名不一致");

                status = false;
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
                resXml = SWxPayUtils.getWxpayCallbackFailReturn("签名不一致");
            }
        }

        // 保存回调结果
        payOrderCallbackService.saveCallbackInfo(payNo, status, notifyData);

        log.info("通知微信服务器的报文：{}", resXml);
        SResponseUtils.outputStr(response, resXml);
    }
}
